package com.jf.mall.dao;

import com.jf.mall.utils.JDBCUtilsByDruid;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ColumnListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created with IntelliJ IDEA
 * Description:BasicDao开发
 * User:22954
 * Date:2024-09-13
 * Time:20:39
 */
public class BasicDAO<T> {
    private final QueryRunner qr = new QueryRunner();

    /**
     * 查询多条结果
     * @param sql 待执行的sql语句
     * @param clazz 需封装的类的Class对象
     * @param params 参数列表
     * @return 查询的结果集合
     */
    public List<T> queryMulti(String sql, Class<T> clazz, Object... params) {
        Connection connection = null;
        connection = JDBCUtilsByDruid.getConnection();
        try {
            return qr.query(connection, sql, new BeanListHandler<T>(clazz), params);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 查询多条结果,并根据主键封装成Map
     * @param sql 待执行的sql语句
     * @param clazz 需要封装的类的Class对象
     * @param idField 主键名字  (主键需为整型)
     * @param params 参数列表
     * @return 查询的结果的Map
     */
    public Map<Integer, T> queryMultiMap(String sql, Class<T> clazz, String idField, Object... params) {
        Connection connection = null;
        connection = JDBCUtilsByDruid.getConnection();
        try {
            List<T> resultList = qr.query(connection, sql, new BeanListHandler<T>(clazz), params);
            Map<Integer, T> resultMap = new HashMap<Integer, T>();
            String method = "get" + capitalize(idField);
            for (T item : resultList) {
                int id = (Integer) clazz.getMethod(method).invoke(item);
                resultMap.put(id, item);
            }
            return resultMap;
        } catch (SQLException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 查询单条结果
     * @param sql 待执行的sql语句
     * @param clazz 需封装的类的Class对象
     * @param params 参数列表
     * @return 查询的单行结果
     */
    public T querySingle(String sql, Class<T> clazz, Object... params) {
        Connection connection = null;
        connection = JDBCUtilsByDruid.getConnection();
        try {
            return qr.query(connection, sql, new BeanHandler<T>(clazz), params);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 查询单行单列结果
     * @param sql 待执行的sql语句
     * @param params 参数列表
     * @return 查询到的单行单列结果
     */
    public Object queryScalar(String sql, Object... params) {
        Connection connection = null;
        connection = JDBCUtilsByDruid.getConnection();
        try {
            return qr.query(connection, sql, new ScalarHandler<>(), params);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 通用DML方法
     * @param sql 待执行的sql语句
     * @param params 参数列表
     * @return 受影响的行数
     */
    public int update(String sql, Object... params) {
        Connection connection = null;
        connection = JDBCUtilsByDruid.getConnection();
        try {
            return qr.update(connection, sql, params);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将首字母大写  工具方法,用于反射获得属性方法
     * @param field 属性名
     * @return 首字母大写的属性名
     */
    private String capitalize(String field) {
        if (field == null || field.isEmpty()) {
            return field;
        }
        return field.substring(0, 1).toUpperCase() + field.substring(1);
    }

    public <E> List<E> querySingleList(String sql, Class<E> clazz,Object... params) {
        Connection connection = null;
        connection = JDBCUtilsByDruid.getConnection();
        try {
            return qr.query(connection, sql, new ColumnListHandler<>(), params);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}
